#include "customizedopenglwidget.h"

CustomizedOpenGLWidget::CustomizedOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
    currentShape = shape::None;
}

void CustomizedOpenGLWidget::startDrawRect(bool state)
{
    if (state) {
        currentShape = shape::Rect;
    }
    else {
        currentShape = shape::None;
    }
}

void CustomizedOpenGLWidget::startDrawTriangle(bool state)
{
    if (state) {
        currentShape = shape::Triangle;
    }
    else {
        currentShape = shape::None;
    }
}

void CustomizedOpenGLWidget::setPolygonMode(bool state)
{
    polygonMode = state;
}

void CustomizedOpenGLWidget::clearCanvas(bool state)
{
    update();
}

void CustomizedOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shader.vert");
    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shader.frag");
    shaderProgram.link();

    // 生成缓冲对象
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);
}

void CustomizedOpenGLWidget::paintGL()
{
    if (polygonMode)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    else
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glBindVertexArray(VAO); // 绑定 VAO
    glBindBuffer(GL_ARRAY_BUFFER, VBO); // 绑定 VBO, 传入顶点数据
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
    glEnableVertexAttribArray(0);

    if (currentShape == shape::Rect) {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // 绑定 EBO，设置矩形顶点的索引数据

        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(int), indices.data(), GL_STATIC_DRAW);

        shaderProgram.bind();
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // 解绑 EBO
    }
    else if(currentShape == shape::Triangle){
        shaderProgram.bind();
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }

    glBindVertexArray(0);  // 解绑 VAO
    glBindBuffer(GL_ARRAY_BUFFER, 0);  // 解绑 VBO
    vertices.clear();
    indices.clear();
}

void CustomizedOpenGLWidget::resizeGL(int w, int h)
{
    Q_UNUSED(w);
    Q_UNUSED(h);
}

void CustomizedOpenGLWidget::mousePressEvent(QMouseEvent *event)
{
    isMousePressed = true;
    lastPos = event->pos();
    mousePressPos = event->pos();
    QOpenGLWidget::mousePressEvent(event);
}

void CustomizedOpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    currentPos = event->pos();

    if (currentShape == shape::Rect) {
        drawRect(mousePressPos, currentPos);
    }
    else if (currentShape == shape::Triangle) {
        drawTriangle(mousePressPos, currentPos);
    }

    QOpenGLWidget::mouseMoveEvent(event);
}

void CustomizedOpenGLWidget::mouseReleaseEvent(QMouseEvent *event)
{
    isMousePressed = false;
    currentPos = event->pos();
    if (currentShape == shape::Rect){
        drawRect(mousePressPos, currentPos);
    }
    else if (currentShape == shape::Triangle) {
        drawTriangle(mousePressPos, currentPos);
    }
    QOpenGLWidget::mouseReleaseEvent(event);
}

float CustomizedOpenGLWidget::getNormalizedX(int x)
{
    return (float(x) - size().width()/2)/(size().width()/2);
}

float CustomizedOpenGLWidget::getNormalizedY(int y)
{
    return -(float(y) - size().height()/2)/(size().height()/2);
}

void CustomizedOpenGLWidget::drawRect(QPoint beginPos, QPoint endPos)
{
    // 计算矩形四个顶点的位置
    float beginX = getNormalizedX(beginPos.x());
    float beginY = getNormalizedY(beginPos.y());
    float endX = getNormalizedX(endPos.x());
    float endY = getNormalizedY(endPos.y());

    // qDebug() << beginX << "-" << beginY << "-" << endX << "-" << endY;

    vertices = {
        beginX, beginY, 0.0,
        endX, beginY, 0.0,
        beginX, endY, 0.0,
        endX, endY, 0.0
    };

    indices = {
        0, 1, 2,
        1, 2, 3
    };

    update();
}

void CustomizedOpenGLWidget::drawTriangle(QPoint beginPos, QPoint endPos)
{
    // 计算三角形三个顶点的位置
    float beginX = getNormalizedX(beginPos.x());
    float beginY = getNormalizedY(beginPos.y());
    float endX = getNormalizedX(endPos.x());
    float endY = getNormalizedY(endPos.y());

    vertices = {
        beginX, beginY, 0.0,
        beginX, endY, 0.0,
        endX, endY, 0.0
    };

    update();
}
